package com.client;

import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.GroupLayout.*;
import javax.swing.LayoutStyle.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.metier.logique.*;
import com.metier.persistance.*;
import org.eclipse.wb.swing.FocusTraversalOnArray;
import java.awt.Dimension;
import java.awt.Cursor;

/**
 * @name DialogAddLieu
 * @description Formulaire d'ajout de lieux.
 * @method DialogAddLieu - Constructeur par défaut appelant la méthode de chargement de la fenêtre.
 * @method buildDialog - Créée le formulaire.
 * @method afficherCarte - Récupère les valeurs des textBox, les vérifies et affiche la carte.
 * @method refreshLblZoom - Modifie le label affichant le niveau du zoom.
 * @method checkBtnMettreJour - Active le bouton Valider si toutes les conditions sont remplies.
 * 
 * @method keyReleased - Événement sur relachement d'une touche, utilisé pour détecter les validations du formulaire via la touche entrée.
 * @method stateChanged - Utilisée par le JSlider permettant de mettre à jour le zoom à chaque changement de valeur.
 * @method mouseWheelMoved - Événement sur le roulement de la molette de la souris. Permet de zoomer-dézoomer sur la carte via la molette.
 * @author Ambroise
 *
 */
public class DialogAddLieu extends JDialog implements ActionListener, KeyListener, MouseListener, ChangeListener, MouseWheelListener, ItemListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTextField txtNom;
	private JTextArea txtDescription;
	private JButton btnMettreJour;
	private JLabel lblDescription;
	private JLabel lblNomDuPoi;
	private JLabel lblPOI;
	private JButton btnAnnuler;
	private JTextField txtVille;
	private JTextField txtPays;
	private JGoogleMapEditorPan oGoogleMapEditorPan;
	private JButton btnGnrerLaCarte;
	private JLabel lblZoom;
	private JLabel lblZoomValue;
	private JSlider zoom;
	private int fenetreChargee = 0;
	private JComboBox cbbTypeMap;
	
	/**
	 * @name DialogAddLieu
	 * @description Constructeur par défaut appelant la méthode de chargement de la fenêtre.
	 */
	public DialogAddLieu() {
		buildDialog();
	}
	
	/**
	 * @name buildDialog
	 * @description Créée le formulaire.
	 */
	public void buildDialog(){
		setTitle("Création d'un lieu");
		setLocationRelativeTo(null);
		setSize(665, 850);
		setResizable(false);
		setModal(true);
		setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		this.setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/16, (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/8);
		
		lblNomDuPoi = new JLabel("Nom du Lieu :");
		
		txtNom = new JTextField();
		lblNomDuPoi.setLabelFor(txtNom);
		txtNom.setColumns(10);
		this.txtNom.addKeyListener(this);
		
		lblDescription = new JLabel("Description : ");
		
		txtDescription = new JTextArea();
		lblDescription.setLabelFor(txtDescription);
		
		btnMettreJour = new JButton();
		btnMettreJour.setText("Valider");
		btnMettreJour.addActionListener(this);
		// On désactive le bouton tant que la carte n'a pas été générée au moins une fois.
		this.btnMettreJour.setEnabled(false);
		
		btnAnnuler = new JButton("Annuler");
		btnAnnuler.addActionListener(this);
		
		JLabel lblVille = new JLabel("<html><body><u>Ville</u></body></html>");
		lblVille.setToolTipText("Entrez le nom de la ville ou le nom d'un lieu ou la latitude");
		
		txtVille = new JTextField();
		lblVille.setLabelFor(txtVille);
		txtVille.setColumns(10);
		this.txtVille.addKeyListener(this);
		
		JLabel lblPays = new JLabel("<html><body><u>Pays</u>&nbsp;(Optionnel)</body></html>");
		lblPays.setToolTipText("Entrez le nom du pays ou la longitude");
		
		txtPays = new JTextField();
		lblPays.setLabelFor(txtPays);
		txtPays.setColumns(10);
		this.txtPays.addKeyListener(this);
		
		oGoogleMapEditorPan = new JGoogleMapEditorPan();
		oGoogleMapEditorPan.setZoom(14);
		oGoogleMapEditorPan.setWidth(630);
		oGoogleMapEditorPan.setMinimumSize(new Dimension(630, 450));
		oGoogleMapEditorPan.setHeight(450);
		oGoogleMapEditorPan.setFocusable(false);
		this.oGoogleMapEditorPan.addMouseWheelListener(this);
		
		btnGnrerLaCarte = new JButton("Générer la carte");
		this.btnGnrerLaCarte.addActionListener(this);
		
		zoom = new JSlider();
		this.zoom.addMouseListener(this);
		this.zoom.addChangeListener(this);
		zoom.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		zoom.setToolTipText("Réglez le zoom entre 1 et 21");
		zoom.setMinorTickSpacing(1);
		zoom.setMinimum(1);
		zoom.setMaximum(21);
		zoom.setValue(12);
		
		lblZoomValue = new JLabel("12");
		
		lblZoom = new JLabel("Zoom :");
		
		cbbTypeMap = new JComboBox();
		cbbTypeMap.addItem("Terrain");
		cbbTypeMap.addItem("Roadmap");
		cbbTypeMap.addItem("Satellite");
		cbbTypeMap.addItem("Hybrid");
		// On prend roadmap par défaut.
		cbbTypeMap.setSelectedItem("Roadmap");
		cbbTypeMap.addItemListener(this);
		
		GroupLayout groupLayout = new GroupLayout(getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addContainerGap()
							.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
								.addGroup(groupLayout.createSequentialGroup()
									.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
										.addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false)
											.addComponent(lblVille, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
											.addComponent(txtVille, GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE))
										.addComponent(cbbTypeMap, GroupLayout.PREFERRED_SIZE, 88, GroupLayout.PREFERRED_SIZE))
									.addGap(64)
									.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
										.addComponent(zoom, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
											.addComponent(lblPays, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
											.addComponent(txtPays, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE))))
								.addComponent(txtDescription, GroupLayout.PREFERRED_SIZE, 324, GroupLayout.PREFERRED_SIZE)
								.addComponent(lblNomDuPoi)
								.addComponent(txtNom, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE)
								.addComponent(lblDescription)
								.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
									.addGroup(groupLayout.createSequentialGroup()
										.addComponent(btnGnrerLaCarte)
										.addGap(138)
										.addComponent(btnAnnuler)
										.addPreferredGap(ComponentPlacement.RELATED)
										.addComponent(btnMettreJour))
									.addComponent(oGoogleMapEditorPan, GroupLayout.PREFERRED_SIZE, 632, GroupLayout.PREFERRED_SIZE))))
						.addGroup(groupLayout.createSequentialGroup()
							.addGap(261)
							.addComponent(lblZoom)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(lblZoomValue)))
					.addContainerGap(17, Short.MAX_VALUE))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(lblNomDuPoi)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(txtNom, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(lblDescription)
					.addGap(5)
					.addComponent(txtDescription, GroupLayout.PREFERRED_SIZE, 96, GroupLayout.PREFERRED_SIZE)
					.addGap(18)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblVille)
						.addComponent(lblPays))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(txtVille, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(txtPays, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.RELATED, 21, Short.MAX_VALUE)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblZoomValue)
						.addComponent(lblZoom))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addComponent(zoom, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(cbbTypeMap, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(oGoogleMapEditorPan, GroupLayout.PREFERRED_SIZE, 450, GroupLayout.PREFERRED_SIZE)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGap(33)
							.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
								.addComponent(btnMettreJour)
								.addComponent(btnAnnuler)))
						.addGroup(groupLayout.createSequentialGroup()
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(btnGnrerLaCarte)))
					.addContainerGap())
		);
		getContentPane().setLayout(groupLayout);
		getContentPane().setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[]{txtNom, txtDescription, btnMettreJour, btnAnnuler}));
		
	}
	
	/**
	 * @name afficherCarte
	 * @description Récupère les valeurs des textBox, les vérifies et affiche la carte.
	 */
	private void afficherCarte(){
		if(!this.txtVille.getText().isEmpty()){
			try {
				this.oGoogleMapEditorPan.setZoom(this.zoom.getValue());
				this.oGoogleMapEditorPan.getMapByLocation(this.txtVille.getText(), this.txtPays.getText());
				checkBtnMettreJour();
			} catch (Exception e1) {
				if(ConfigurationProjet.MODE_DEBUG){
					System.out.println("Erreur dans "+this.getClass().getSimpleName()+", impossible de générer la carte avec le couple Pays/Ville.");
					e1.printStackTrace();
				}
			}
		}else{
			JOptionPane.showMessageDialog(null, "Le champ Ville est obligatoire avant de générer la carte.", "Attention !", JOptionPane.INFORMATION_MESSAGE);
		}
	}
	
	/**
	 * @name refreshLblZoom
	 * @description Modifie le label affichant le niveau du zoom.
	 */
	private void refreshLblZoom(){
		Object zoomActuel = this.zoom.getValue();
		this.lblZoomValue.setText(zoomActuel.toString());
	}
	
	/**
	 * @name checkBtnMettreJour
	 * @description Active le bouton Valider si toutes les conditions sont remplies.
	 */
	private void checkBtnMettreJour(){
		if(!this.txtNom.getText().isEmpty() && !this.txtVille.getText().isEmpty() && !this.oGoogleMapEditorPan.getUrl().isEmpty()){
			// Si les champs voulus sont remplis on active le bouton.
			this.btnMettreJour.setEnabled(true);
		}else{
			// Sinon on le désactive.
			this.btnMettreJour.setEnabled(false);
		}
	}
	/* 
	 * **************************
	 * Méthodes évènementielles:
	 * **************************
	 */
	
	@Override
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		if(source == this.btnGnrerLaCarte){
			afficherCarte();
		}else if (source == btnMettreJour) {
			if(!this.txtNom.getText().isEmpty() && !this.txtVille.getText().isEmpty() && !this.oGoogleMapEditorPan.getUrl().isEmpty()){
				// Si le nom du lieu et sa ville ne sont pas vide et que la googleMap a été générée alors on enregistre le lieu en BDD.
				if(!(this.txtNom.getText().toString().length() < 3) ){
					// Si le nom est de plus de 3 caractères				
					MSG oMSG = new MSG();
					Carte carte = new Carte();
					SimpleDateFormat formater = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); 
					Date date = new Date(); 
					
					// On met les données dans le MSG.
					oMSG.setData("NOM", this.txtNom.getText());
					oMSG.setData("DESCRIPTIF", this.txtDescription.getText());
					oMSG.setData("URL", this.oGoogleMapEditorPan.getUrl());
					oMSG.setData("DATE_CREATION", formater.format(date));
					oMSG.setData("DATE_MODIFICATION", formater.format(date));
					
					// On insère le lieu en BDD.
					carte.insert(oMSG);
					
					// On met à jour la CBB des lieux.
					
					
					// On cache le formulaire.
					setVisible(false);
					
				}else{
					JOptionPane.showMessageDialog(null, "Le nom du lieu doit faire au moins 3 caractères.", "Nom incomplet !", JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}else if(source == this.btnAnnuler){
			this.setVisible(false);
		}

	}

	@Override
	public void keyTyped(KeyEvent e) {}

	@Override
	public void keyPressed(KeyEvent e) {
		Object source = e.getSource();
		
		if(source == this.txtNom){
			checkBtnMettreJour();
		}
	}

	/**
	 * @name keyReleased
	 * @description Événement sur relachement d'une touche, utilisé pour détecter les validations du formulaire via la touche entrée.
	 */
	@Override
	public void keyReleased(KeyEvent e) {
		Object source = e.getSource();
		char keyChar = e.getKeyChar();
		int keyCode = e.getKeyCode();
		
		if(source == this.txtPays || source == this.txtVille){
			// Si la source est la JTextField Pays ou Ville
			if(keyCode == 10){
				// Si appui sur la touche entrée.
				afficherCarte();// On met à jour la carte.
			}
		}else if(keyCode == 27){
			// Bouton echap
			this.setVisible(false);
		}
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		Object source = e.getSource();
		
		if(source == this.zoom){
			afficherCarte();
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * @name stateChanged
	 * @description Utilisée par le JSlider permettant de mettre à jour le zoom à chaque changement de valeur.
	 */
	@Override
	public void stateChanged(ChangeEvent e) {
		Object source = e.getSource();

		// On fait un try/catch afin d'éviter que si le JSlider venait à faire plus de 3 appels nativement on se retrouve avec une erreur sortie d'on-ne-sais-où.
		try{
			if(source == this.zoom){
				// Si notre source est le zoom
				if(this.fenetreChargee >= 3){
					// Si on est au moins au 3ème appel de cette méthode alors on l'utilise.
					// En effet, cette méthode est appelée 3 fois avant le chargement complet de la fenêtre.
					if(source == this.zoom){
						refreshLblZoom();
					}
				}else{
					this.fenetreChargee++;
				}
			}
		}catch (Exception ex) {
			if(ConfigurationProjet.MODE_DEBUG){
				System.out.println("Une erreur est survenue lors de l'appel de la méthode"+this.getClass().getSimpleName()+".stateChanged(zoom). (Lors du "+this.fenetreChargee+" ème appel de la méthode.)");
				ex.printStackTrace();
			}
		}
	}

	/**
	 * @name mouseWheelMoved
	 * @description Événement sur le roulement de la molette de la souris. Permet de zoomer-dézoomer sur la carte via la molette.
	 */
	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		int mouvementMolette = e.getWheelRotation();
		this.zoom.setValue(this.zoom.getValue() - mouvementMolette);
		refreshLblZoom();
		afficherCarte();
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		Object source = e.getSource();
		
		if (source == cbbTypeMap) {
			try {
				this.oGoogleMapEditorPan.refresh(new MSG("roadmap",cbbTypeMap.getSelectedItem().toString().toLowerCase()));
			} catch (Exception ex) {
				if(ConfigurationProjet.MODE_DEBUG){
					System.out.println("Le type de carte a été changé mais la carte n'a pas encore été créée.");
					ex.printStackTrace();
				}
			}
		}
	}
}
